/*
 * This file is part of Cadmium.
 * Copyright (C) 2007-2010 Xavier Clerc.
 *
 * Cadmium is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Cadmium is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package fr.x9c.cadmium.primitives.str;

/**
 * This class is the translation/implementation of C type 'backtrack_point'
 * (union type with pointers of pointers).
 *
 * @author <a href="mailto:cadmium@x9c.fr">Xavier Clerc</a>
 * @version 1.0
 * @since 1.0
 */
final class BacktrackPoint {

    /** Tag indicating that 'loc' field is a starting index. */
    static final int START_TAG = 1;

    /** Tag indicating that 'loc' field is a ending index. */
    static final int END_TAG = 2;

    /** Tag indicating that 'loc' field is a register. */
    static final int REGISTER_TAG = 3;

    /** Indicates whether the backtrack point is a 'pos'. */
    private final boolean pos;

    /**
     * Represents 'pos.pc' field (if pos is <tt>true</tt>)
     * or 'undo.loc' field (if pos is <tt>false</tt>).
     */
    private final int x;

    /**
     * Represents 'pos.txt' field (if pos is <tt>true</tt>)
     * or 'undo.val' field (if pos is <tt>false</tt>).
     */
    private final int y;

    /**
     * Constructs a backtrack point.
     * @param p whether the point is a 'pos'
     * @param x 'pos.pc' or 'undo.loc' according to <tt>p</tt>
     * @param y 'pos.txt' or 'undo.val' according to <tt>p</tt>
     */
    private BacktrackPoint(final boolean p, final int x, final int y) {
        this.pos = p;
        this.x = x;
        this.y = y;
    } // end constructor(boolean, int, int)

    /**
     * Constructs a 'pos' backtrack point.
     * @param pc value of 'pc' field
     * @param txt value of 'txt' field
     * @return 'pos' backtrack point
     */
    static BacktrackPoint makePos(final int pc, final int txt) {
        return new BacktrackPoint(true, pc, txt);
    } // end method 'makePos(int, int)'

    /**
     * Constructs a 'undo' backtrack point.
     * @param loc value of 'loc' field
     * @param val value of 'val' field
     * @return 'undo' backtrack point
     */
    static BacktrackPoint makeUndo(final int loc, final int val) {
        return new BacktrackPoint(false, loc, val);
    } // end method 'makeUndo(int, int)'

    /**
     * Tests whether the point is a 'pos'.
     * @return <tt>true</tt> if the point is a 'pos',
     *         <tt>false</tt> otherwise
     */
    boolean isPos() {
        return this.pos;
    } // end method 'isPos()'

    /**
     * Returns the value of the 'pos.pc' field.
     * @return the value of the 'pos.pc' field
     */
    int getPc() {
        assert this.pos : "not a 'pos'";
        return this.x;
    } // end method 'getPc()'

    /**
     * Returns the value of the 'pos.txt' field.
     * @return the value of the 'pos.txt' field
     */
    int getTxt() {
        assert this.pos : "not a 'pos'";
        return this.y;
    } // end method 'getTxt()'

    /**
     * Returns the value of the 'undo.loc' field.
     * @return the value of the 'undo.loc' field
     */
    int getLoc() {
        assert !this.pos : "not a 'undo'";
        return this.x;
    } // end method 'getLoc()'

    /**
     * Returns the value of the 'undo.val' field.
     * @return the value of the 'undo.val' field
     */
    int getVal() {
        assert !this.pos : "not a 'undo'";
        return this.y;
    } // end method 'getVal()'

} // end class 'BacktrackPoint'
